#! /usr/bin/env python

import sys
from optparse import OptionParser
import random


class SchedulerCore:
    def __init__(self, seed=0, jobs=3, jlist='', maxlen=10, policy='FIFO', quantum=1, compute=False):
        parser = OptionParser()
        parser.add_option("-s", "--seed", default=seed, help="the random seed",
                          action="store", type="int", dest="seed")
        parser.add_option("-j", "--jobs", default=jobs, help="number of jobs in the system",
                          action="store", type="int", dest="jobs")
        parser.add_option("-l", "--jlist", default=jlist,
                          help="instead of random jobs, provide a comma-separated list of run times",
                          action="store", type="string", dest="jlist")
        parser.add_option("-m", "--maxlen", default=maxlen, help="max length of job",
                          action="store", type="int", dest="maxlen")
        parser.add_option("-p", "--policy", default=policy, help="sched policy to use: SJF, FIFO, RR",
                          action="store", type="string", dest="policy")
        parser.add_option("-q", "--quantum", default=quantum, help="length of time slice for RR policy",
                          action="store", type="int", dest="quantum")
        parser.add_option("-c", default=compute, help="compute answers for me", action="store_true", dest="solve")

        (self.options, self.args) = parser.parse_args()
        self.deal_args()

    def deal_args(self):
        options = self.options
        random.seed(options.seed)

        print('调度算法：', options.policy)
        if options.jlist == '':
            print('任务数量', options.jobs)
            print('任务最大长度', options.maxlen)
            print('随机种子', options.seed)
        else:
            print('任务长度：', options.jlist)

        print('\n任务列表如下：')

        import operator

        joblist = []
        if options.jlist == '':
            for jobnum in range(0, options.jobs):
                runtime = int(options.maxlen * random.random()) + 1
                joblist.append([jobnum, runtime])
                print('  任务', jobnum, '( 长度 = ' + str(runtime) + ' )')
        else:
            jobnum = 0
            for runtime in options.jlist.split(','):
                joblist.append([jobnum, float(runtime)])
                jobnum += 1
            for job in joblist:
                print('  任务', job[0], '( 长度 = ' + str(job[1]) + ' )')
        print('\n')

        if options.solve:
            print('** 解答 **\n')
            if options.policy == 'SJF':
                joblist = sorted(joblist, key=operator.itemgetter(1))
                options.policy = 'FIFO'

            if options.policy == 'FIFO':
                thetime = 0
                print('执行序列:')
                for job in joblist:
                    print('  [ 时间 %3d ] 执行任务%d %.2f 秒 ( 在 %.2f 秒时完成)' % (
                        thetime, job[0], job[1], thetime + job[1]))
                    thetime += job[1]

                print('\n最终统计:')
                t = 0.0
                count = 0
                turnaroundSum = 0.0
                waitSum = 0.0
                responseSum = 0.0
                for tmp in joblist:
                    jobnum = tmp[0]
                    runtime = tmp[1]

                    response = t
                    turnaround = t + runtime
                    wait = t
                    print('  任务%3d -- 响应时间 %3.2f秒  周转时间 %3.2f秒  等待时间 %3.2f秒' % (
                        jobnum, response, turnaround, wait))
                    responseSum += response
                    turnaroundSum += turnaround
                    waitSum += wait
                    t += runtime
                    count += 1
                print('\n  平均 -- 响应时间 %3.2f秒  周转时间 %3.2f秒  等待时间 %3.2f秒\n' % (
                    responseSum / count, turnaroundSum / count, waitSum / count))

            if options.policy == 'RR':
                print('执行序列:')
                turnaround = {}
                response = {}
                lastran = {}
                wait = {}
                quantum = float(options.quantum)
                jobcount = len(joblist)
                for i in range(0, jobcount):
                    lastran[i] = 0.0
                    wait[i] = 0.0
                    turnaround[i] = 0.0
                    response[i] = -1

                runlist = []
                for e in joblist:
                    runlist.append(e)

                thetime = 0.0
                while jobcount > 0:
                    # print '%d jobs remaining' % jobcount
                    job = runlist.pop(0)
                    jobnum = job[0]
                    runtime = float(job[1])
                    if response[jobnum] == -1:
                        response[jobnum] = thetime
                    currwait = thetime - lastran[jobnum]
                    wait[jobnum] += currwait
                    if runtime > quantum:
                        runtime -= quantum
                        ranfor = quantum
                        print('  [ 时间 %3d ] 执行任务%3d %.2f 秒' % (thetime, jobnum, ranfor))
                        runlist.append([jobnum, runtime])
                    else:
                        ranfor = runtime
                        print('  [ 时间 %3d ] 执行任务%3d %.2f 秒 ( 在 %.2f 秒时完成 )' % (
                            thetime, jobnum, ranfor, thetime + ranfor))
                        turnaround[jobnum] = thetime + ranfor
                        jobcount -= 1
                    thetime += ranfor
                    lastran[jobnum] = thetime

                print('\n最终统计:')
                turnaroundSum = 0.0
                waitSum = 0.0
                responseSum = 0.0
                for i in range(0, len(joblist)):
                    turnaroundSum += turnaround[i]
                    responseSum += response[i]
                    waitSum += wait[i]
                    print(
                        '  任务%3d -- 响应时间 %3.2f秒  周转时间 %3.2f秒  等待时间 %3.2f秒' % (
                            i, response[i], turnaround[i], wait[i]))
                count = len(joblist)

                print('\n  平均 -- 响应时间 %3.2f秒  周转时间 %3.2f秒  等待时间 %3.2f秒\n' % (
                    responseSum / count, turnaroundSum / count, waitSum / count))

            if options.policy != 'FIFO' and options.policy != 'SJF' and options.policy != 'RR':
                print('错误: 不支持', options.policy)
                sys.exit(0)
        else:
            print('请计算每一个任务的周转时间，响应时间，等待时间，'
                  '你可以打开答案模式来查看答案，或者修改随机种子来得到不一样的问题')


def main():
    core = SchedulerCore()


if __name__ == "__main__":
    main()
